<?php
/**
 * Class derived from an adaption of Tom Carlson's API class used to create and manage Jabber users on Dreamhost shared hosting servers.
 * 
 * Traditionally, there was no way to programmatically add or remove users from Dreamhost's servers. This has been a frequently requested
 * feature in the Dreamhost forums. Now, with the release of the Dreamhost API there is a way. The Dreamhost class provides a PHP wrapper 
 * around the full API. The derived DHJabberUserManager provides a function for each Jabber related command and a way to check the status 
 * of scheduled service commands.
 * These classes require a Dreamhost API key which can be obtained through the Web Panel API page of the Dreamhost web panel.
 * @package dreamhost_jabber_chat
 * @subpackage dreamhost_api_user_manager
 */
/**
 * Class for interacting with Dreamhost API
 * 
 * Dreamhost is a hosting company in Los Angelas.  They released a small API
 * for users of their private servers to interact with their accounts.
 * This API is described at http://wiki.dreamhost.com/Api
 * 
 * This class provides an easy way to quickly add Dreamhost API functionality
 * to your existing dashboard or management console.
 * 
 * This class has been modified slightly to improve encapsulation.
 * 
 * @package dreamhost_jabber_chat
 * @subpackage dreamhost_api_user_manager
 * @version 0.1  05/31/2010
 * @author Tom Carlson (http://elance.com/s/tomcarlson/resume)
 * @link http://tomcarlson.com
 * 
 */
 
class Dreamhost {	
	/* available for status and debug */
  public $http_code;  /* Contains the last HTTP status code returned. */  
  public $http_info;  /* Contains the last HTTP headers returned.     */  
  public $url;        /* Contains the last API call.                  */  
   
  /* May be set externally with setter functions */ 
  protected $key;              /* Dreamhost API Key */  
  protected $format = 'xml';   /* Response format. */     
  protected $account;          /* The account number to perform operations under. */ 
    
  protected $api_url = 'https://api.dreamhost.com/'; /* Dreamhost API base url */ 
  protected $timeout = 30;                           /* Set timeout default.   */  
  protected $connecttimeout = 30;                    /* Set connect timeout.   */ 
  protected $ssl_verifypeer = FALSE;                 /* Verify SSL Cert.       */  
  protected $useragent = 'DreamhostAPI_THC v0.1';    /* Set the useragent.     */

  function __construct($dreamhost_api_key) {
    $this->key = $dreamhost_api_key;
  }

  public function format($newformat) {
    $this->format = $newformat;
  }
  
  public function account($newaccount) {
    $this->account = $newaccount;
  }
  
  // Make an HTTP request and return API results
  function http($url, $method, $parameters = NULL) {
    $this->http_info = array();
    $ci = curl_init();
    /* Curl settings */
    curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
    curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout);
    curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout);
    curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:'));
    curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
    curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader'));
    curl_setopt($ci, CURLOPT_HEADER, FALSE);

    switch ($method) {
      case 'GET':
        $pcount = 0;        
        foreach ($parameters as $key=>$value)
        {
        	if (!$pcount)
        	  $url .= '?'.$key.'='.urlencode($value);
        	else
        	  $url .= '&'.$key.'='.urlencode($value);
        	$pcount++;
        }
        break;    	
      case 'POST':
        $postfields = $parameters;
        curl_setopt($ci, CURLOPT_POST, TRUE);
        if (!empty($postfields)) {
          curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
        }
        break;
      case 'DELETE':
        $postfields = $parameters;
        curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
        if (!empty($postfields)) {
          $url = "{$url}?{$postfields}";
        }
    }
    var_dump($url);
    curl_setopt($ci, CURLOPT_URL, $url);
    $response = curl_exec($ci);
    $this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
    $this->http_info = array_merge($this->http_info, curl_getinfo($ci));
    $this->url = $url;
    curl_close ($ci);
    return $response;
  }

  // Get header info to store.  Used by CURLOPT_HEADERFUNCTION
  function getHeader($ch, $header) {
    $i = strpos($header, ':');
    if (!empty($i)) {
      $key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
      $value = trim(substr($header, $i + 2));
      $this->http_header[$key] = $value;
    }
    return strlen($header);
  }
  
  
  public function api($command,$extraparams = NULL)
  {
  	$baseparams = array('key'=>$this->key,'unique_id'=>uniqid(),'cmd'=>trim($command),'format'=>$this->format);
  	if ($this->account) $baseparams = array_merge($baseparams,array('account'=>$this->account));
  	  
  	if (is_array($extraparams))
  	  $parameters = array_merge($baseparams,$extraparams);
  	else
  	  $parameters = $baseparams;
  	return $this->http($this->api_url,'GET',$parameters);
  }
}

/**
 * Class providing functions to access all Jabber related commands provided by the Dreamhost API.
 * 
 * If a command is enqued to run as a service and doesn't immediately run, the API returns a "service token". 
 * In this case the class stores the token and the server response status string in an array as a $token=>$status pair and returns the token and result of a status check packed into an array to the caller.  This array can be used with list() like this: list($token, $status) = addUser($username, $domain, $password).
 * A function is provided to check the status of all still pending requests or a particular request if passed a token string.
 * 
 * @package dreamhost_jabber_chat
 * @subpackage dreamhost_api_user_manager
 * @author SinthiaV Fireflow Design
 * @copyright 2011
 * @version 0.1
 * @access public
 *
 */
class DHJabberUserManager extends Dreamhost
{
    /**
     * Array of servuce tokens in the format $token=>$status, where $token and $status are strings obtained from the Dresmhost API and cannot be set directly.
     * @var array
     * @access private
     */
    private $service_tokens = array();
    
    /**
     * Constructs a new DHJabberUserManager object and sets it's dreamhost API key. The API key is obtained through the Web Panel API page of the Dreamhost web panel.
     * At a minimum this API key must have access to jabber-* and services-progress functions.
     * @param string $dreamhost_api_key
     */
    public function __construct($dreamhost_api_key)
    {
        $this->format('php');
        parent::__construct($dreamhost_api_key);
    }
    
    /**
     * Adds a token to the $service_tokens array (if it hassn't already been added by a previous request) and returns result of a call to checkServiceTokenStatus().
     * @param string $token
     * @return string
     * @internal helper function
     */
    protected function addServiceToken($token)
    {
        if(!array_key_exists($token, $this->service_tokens)) 
            $this->service_tokens[$token] = 'waiting'; 
        return $this->checkServiceTokenStatus($token);
    }

    /**
     * Issues a service request for a new Jabber user at the given domain with the given name and password. 
     * Returns an array with the service token string at index[0] and the status of the request at index[1].
     * @see DHJabberUserManager
     * @param string $username
     * @param string $domain
     * @param string $password
     * @return Array 
     */
    public function addUser($username, $domain, $password) 
    {
        $command = 'jabber-add_user';
        $result = unserialize($this->api($command, array('username'=>$username, 'domain'=>$domain, 'password'=>$password)));
        if( $result['result'] == 'success') 
        {
            $token = $result['data'][0]['token'];
            $status = $this->addServiceToken($token);
        }
        else 
        {
            $status = array('error', $result['result']);
        }
        return $status;
    }
    
    /**
     * Issues a service request to remove a Jabber user with the given name and password. 
     * Returns an array with the service token string at index[0] and the status of the request at index[1].
     * @see DHJabberUserManager
     * @param string $username
     * @param string $password
     * @return Array 
     */
    public function removeUser($username, $domain) 
    {
        $command = 'jabber-remove_user';
        $result = unserialize($this->api($command, array('username'=>$username, 'domain'=>$domain)));
        if( $result['result'] == 'success') 
        {
            $token = $result['data'][0]['token'];
            $status = $this->addServiceToken($token);
        }
        else 
        {
            $status = array('error', $result['result']);
        }
        return $status;
    }
    
    /**
    * Issues a service request to reactivate an inactive existing Jabber user with the given name and password.
    * Returns an array with the service token string at index[0] and the status of the request at index[1].
    * @see DHJabberUserManager
    * @param string $username
    * @param string $password
    * @return Array
    */
    public function reactivateUser($username, $domain)
    {
        $command = 'jabber-reactivate_user';
        $result = unserialize($this->api($command, array('username'=>$username, 'domain'=>$domain)));
        if( $result['result'] == 'success') 
        {
            $token = $result['data'][0]['token'];
            $status = $this->addServiceToken($token);
        }
        else 
        {
            $status = array('error', $result['result']);
        }
        return $status;
    }
    
    /**
    * Issues a service request to deactivate an existing Jabber user with the given name and password.
    * Returns an array with the service token string at index[0] and the status of the request at index[1].
    * @see DHJabberUserManager
    * @param string $username
    * @param string $password
    * @return Array
    */
    public function deactivateUser($username, $domain)
    {
        $command = 'jabber-deactivate_user';
        $result = unserialize($this->api($command, array('username'=>$username, 'domain'=>$domain)));
         if( $result['result'] == 'success') 
        {
            $token = $result['data'][0]['token'];
            $status = $this->addServiceToken($token);
        }
        else 
        {
            $status = array('error', $result['result']);
        }
        return $status;
    }
    
    /**
     * Returns an array of arrays representing jabber users with the following fields username, domain, password and status.
     * If 
     * @param bool $show_passwords
     * @return array
     */
    public function listUsers($show_passwords=false)
    {
        if ( $show_passwords ) $command = 'jabber-list_users';
        else $command = 'jabber-list_users_no_pw';
        $result = unserialize($this->api($command));
        if($result['result'] == 'success') return $result['data'];
    }
    
    /**
     * Returns an array of domains which can support Jabber in an array
     * @return array
     */
    public function listJabberDomains()
    {
        $command = 'jabber-list_valid_domains';
        $result = unserialize($this->api($command));
        if($result['result'] == 'success') 
        {
            $data = array();
            foreach($result['data'] as $item)
            {
                $data[] = $item['domain'];
            }
        }
        else
        {
            $data =array('error'=> $result['result']);
        }
        return $data;   
    }
    
    /**
     * Updates the status of all of the service-tokens still pending and returns an array of token=>status pairs. If a token is specified only that is returned.
     * @param string $token
     * @return array
     * @see DHJabberUserManager
     */
    public function checkServiceTokenStatus($token = false)
    {
        $command = "services-progress";
        if(isset($token) && !(array_key_exists($token, $this->service_tokens))) $this->addServiceToken($token);
        foreach ($this->service_tokens as $tok=>$status)
        {
            if($status=='waiting')
            {
                $result = unserialize($this->api($command, array('token'=>$tok)));
                if($result['result']=='success') 
                    $status = $result['data'][0]['status'];
                else
                    $status = $result['data'];
            }
            if($token == $tok) return array($token=>$status);
        }
        return $this->service_tokens;
    }
    
}
?>